home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / oldwish / wishGather.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-07-13  |  27.7 KB  |  1,113 lines

  1. /* 
  2.  * wishGather.c --
  3.  *
  4.  *    Gathering and sorting file names.  Putting them in
  5.  *    data structures.
  6.  *
  7.  * Copyright 1987 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /a/newcmds/wish/RCS/wishGather.c,v 1.4 89/01/11 11:31:37 mlgray Exp Locker: mgbaker $ SPRITE (Berkeley)";
  20. #endif not lint
  21.  
  22.  
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <sys/dir.h>
  26. #include <errno.h>
  27. #include "sx.h"
  28. #include "string.h"
  29. #include "util.h"
  30. #include "wishInt.h"
  31.  
  32. /* ClientData for scandir select proc's */
  33. static    ClientData    scanData;
  34.  
  35. /* used before defined */
  36. extern    Boolean    SelectFiles();
  37. extern    int    AlphaForwards();
  38. extern    int    AlphaReverse();
  39. extern    int    AtimeForwards();
  40. extern    int    AtimeReverse();
  41. extern    int    CtimeForwards();
  42. extern    int    CtimeReverse();
  43. extern    int    MtimeForwards();
  44. extern    int    MtimeReverse();
  45. extern    int    DtimeForwards();
  46. extern    int    DtimeReverse();
  47. extern    int    SizeForwards();
  48. extern    int    SizeReverse();
  49. static    int    AtimeSort();
  50. static    int    MtimeSort();
  51. static    int    DtimeSort();
  52. static    int    SizeSort();
  53.  
  54.  
  55. /*
  56.  *----------------------------------------------------------------------
  57.  *
  58.  * WishGatherNames --
  59.  *
  60.  *    Using scandir() and a bunch of rules and call-back thingies,
  61.  *    gather the appropriate names into the appropriate places.
  62.  *
  63.  * Results:
  64.  *    TCL_OK if all went well.  Some TCL error if not.
  65.  *
  66.  * Side effects:
  67.  *    The names are gathered and stuff is allocated.
  68.  *
  69.  *----------------------------------------------------------------------
  70.  */
  71. int
  72. WishGatherNames(aWindow)
  73.     WishWindow    *aWindow;
  74. {
  75.     int        nitems;
  76.     struct    direct    **namelist;
  77.     int        (*compareProc)();
  78.     int        i;
  79.     WishFile    *tmpPtr, *backTmpPtr;
  80.     WishGroup    *grpPtr;
  81.     int        result;
  82.     Boolean    getAttrsP = FALSE;
  83.     struct    stat    attrs;
  84.  
  85.     if (aWindow->groupList == NULL) {
  86.     /* get it out of the file */
  87. #ifdef NOTDEF
  88.     Sx_Panic(wishDisplay,
  89.         "WishGatherNames: Should source .wish file, but can't.");
  90. #endif NOTDEF
  91. #ifdef NOTDEF
  92.     WishReadRules(aWindow, name);
  93. #endif NOTDEF
  94.     }
  95.     if (aWindow->groupList == NULL) {
  96.     /*
  97.      * There wasn't a file, select everything (or should the default
  98.      * be to select nothing?
  99.      */
  100.     aWindow->groupList = (WishGroup *) malloc(sizeof (WishGroup));
  101.     aWindow->groupList->myColumn = -1;
  102.     aWindow->groupList->headerWindow = UNINITIALIZED;
  103.     aWindow->groupList->x = aWindow->groupList->y = -1;
  104.     aWindow->groupList->width = aWindow->groupList->height = -1;
  105.     aWindow->groupList->entry_x = aWindow->groupList->entry_y =
  106.         aWindow->groupList->entry_width = -1;
  107.     aWindow->groupList->fileList = NULL;
  108.     aWindow->groupList->defType = COMPARISON;
  109.     aWindow->groupList->rule = Util_Strcpy(NULL, "*");
  110.     aWindow->groupList->groupBindings = NULL;
  111.     aWindow->groupList->length = -1;
  112.     aWindow->groupList->selectedP = FALSE;
  113.     aWindow->groupList->highlightP = FALSE;
  114.     aWindow->groupList->nextPtr = NULL;
  115.  
  116.     aWindow->numElements = UNINITIALIZED;
  117.     aWindow->numGroups = 1;
  118.     aWindow->numHiddenGroups = 0;
  119.     }
  120.     if (aWindow->numElements >= 0) {
  121.     /*
  122.      * For now, this means this has already been set up, since there's
  123.      * no garbage collection yet.
  124.      */
  125.     return TCL_OK;
  126.     }
  127.     WishGetCompareProc(aWindow, &compareProc, FALSE);
  128.     getAttrsP = WISH_ATTR_NECESSARY_P; 
  129.  
  130.     scanData = (ClientData) aWindow;
  131.     nitems = scandir(aWindow->dir, &namelist, SelectFiles, compareProc);
  132.     /*
  133.      * I use Stat_GetMsg here.  Am I doing it correctly with errno?
  134.      */
  135.     if (nitems < 0) {
  136.     sprintf(aWindow->interp->result, "%s %s %s %s.  %s %s",
  137.         "Directory scan failed in", aWindow->dir, "with error",
  138.         Stat_GetMsg(errno),
  139.         "Either the directory doesn't exist, or it",
  140.         "is unreadable, or we've run out of memory");
  141.     return TCL_ERROR;
  142.     }
  143.     /*
  144.      * For each file, run through all the groups putting a copy of the file
  145.      * into the group if it matches the rule for that group.  This allows
  146.      * one file to show up in all groups that can select it.  If files should
  147.      * only show up in one place, then skip to the next file after we've
  148.      * found one group for it.  Right now, I use the first policy.  Maybe
  149.      * this should be an option.
  150.      *
  151.      * Since the files are in proper sorted order already and I run through
  152.      * them in order, they will come out in proper sorted order inside the
  153.      * groups.
  154.      *
  155.      * NOTE:  This may be way too slow to use Pattern_Match() in 2 passes
  156.      * like this.
  157.      */
  158.     aWindow->numElements = 0;        /* since it's initialized to -1 */
  159.     aWindow->numHiddenGroups = 0;
  160.     for (i = 0; i < nitems; i++) {
  161.     if (getAttrsP) {
  162.         /*
  163.          * If the files were sorted by something involving an attribute,
  164.          * then there should be a way in the sort routines to cache that
  165.          * info so we don't do a second GetAttributes()'s here...
  166.          * This means dealing with the garbage collection aspects too.
  167.          */
  168.         if (lstat(namelist[i]->d_name, &attrs)
  169.             != 0) {
  170.         char    buffer[MAXPATHLEN];
  171.         sprintf(wishErrorMsg, "%s %s.  %s %s.  %s %s.",
  172.             "Couldn't get attributes for file",
  173.             namelist[i]->d_name,
  174.             "Error was",
  175.             Stat_GetMsg(errno),
  176.             "Current dir is",
  177.             getwd(buffer) == NULL ? "NULL" : buffer);
  178.         aWindow->notifierP = TRUE;
  179.         Sx_Notify(wishDisplay, aWindow->surroundingWindow, -1, -1, 0,
  180.             wishErrorMsg,
  181.             NULL, TRUE, "Skip offending file", (char *) NULL);
  182.         aWindow->notifierP = FALSE;
  183.         continue;
  184.         }
  185.     }
  186.     for (grpPtr = aWindow->groupList; grpPtr != NULL;
  187.         grpPtr = grpPtr->nextPtr) {
  188.         result = Pattern_Match(grpPtr->rule, namelist[i]->d_name);
  189.         if (result == 0) {        /* it matched */
  190.         tmpPtr = (WishFile *) malloc(sizeof (WishFile));
  191.         tmpPtr->name = Util_Strcpy(NULL, namelist[i]->d_name);
  192.         if (getAttrsP) {
  193.             tmpPtr->attrPtr = (struct    stat *)
  194.                 malloc(sizeof (struct    stat));
  195.             *(tmpPtr->attrPtr) = attrs;
  196.         } else {
  197.             tmpPtr->attrPtr = NULL;
  198.         }
  199.         tmpPtr->length = -1;
  200.         tmpPtr->x = tmpPtr->y = -1;
  201.         tmpPtr->myColumn = -1;
  202.         tmpPtr->selectedP = FALSE;
  203.         tmpPtr->lineP = FALSE;
  204.         tmpPtr->highlightP = FALSE;
  205.         tmpPtr->myGroupPtr = grpPtr;
  206.         tmpPtr->nextPtr = NULL;
  207.         if (grpPtr->fileList == NULL) {
  208.             grpPtr->fileList = tmpPtr;
  209.         } else {
  210.             /* add file to end of list */
  211.             for (backTmpPtr = grpPtr->fileList;
  212.                 backTmpPtr->nextPtr != NULL;
  213.                 backTmpPtr = backTmpPtr->nextPtr) {
  214.             /* do nothing */
  215.             }
  216.             backTmpPtr->nextPtr = tmpPtr;
  217.         }
  218.         aWindow->numElements++;
  219.         } else if (result < 0) {
  220.         /*
  221.          * I check the rules as they are created, or the following
  222.          * would cause a billion notifiers!  This is just for extreme
  223.          * caution...
  224.          */
  225.         sprintf(wishErrorMsg, "The rule %s contains an error.",
  226.             grpPtr->rule);
  227.         aWindow->notifierP = TRUE;
  228.         Sx_Notify(wishDisplay, aWindow->displayWindow, -1, -1, 0,
  229.             wishErrorMsg, NULL, TRUE, "Continue", NULL);
  230.         aWindow->notifierP = FALSE;
  231.         }
  232.     }
  233.     }
  234.     if (aWindow->hideEmptyGroupsP) {
  235.     for (grpPtr = aWindow->groupList; grpPtr != NULL;
  236.         grpPtr = grpPtr->nextPtr) {
  237.         if (grpPtr->fileList == NULL) {
  238.         aWindow->numHiddenGroups++;
  239.         }
  240.     }
  241.     }
  242.     /*
  243.      * total number of things that could be displayed is the number of files
  244.      * plus the number of visible group headers plus the number of spaces
  245.      * between visible groups.
  246.      */
  247.     aWindow->totalDisplayEntries = aWindow->numElements +
  248.         (2 * (aWindow->numGroups - aWindow->numHiddenGroups)) - 1;
  249.     free_scandir(nitems, &namelist);
  250.  
  251.     return TCL_OK;
  252. }
  253.  
  254. typedef    struct    {
  255.     WishWindow    *aWindow;
  256.     WishGroup        *grpPtr;
  257. } GatherInfo;
  258.  
  259.  
  260. /*
  261.  *----------------------------------------------------------------------
  262.  *
  263.  * WishGatherSingleGroup --
  264.  *
  265.  *    Using scandir() and a bunch of rules and call-back thingies,
  266.  *    gather the appropriate names into the appropriate places.
  267.  *
  268.  * Results:
  269.  *    TCL_OK if all went well.  Some TCL error if not.
  270.  *
  271.  * Side effects:
  272.  *    The names are gathered and stuff is allocated.
  273.  *
  274.  *----------------------------------------------------------------------
  275.  */
  276. int
  277. WishGatherSingleGroup(aWindow, grpPtr)
  278.     WishWindow    *aWindow;
  279.     WishGroup        *grpPtr;
  280. {
  281.     Boolean    getAttrsP = FALSE;
  282.     int        nitems;
  283.     struct    direct    **namelist;
  284.     int        (*compareProc)();
  285.     struct    stat    attrs;
  286.     WishFile    *tmpPtr, *backTmpPtr;
  287.     extern    Boolean    SelectGroupFiles();    /* forward reference */
  288.     int        i;
  289.     GatherInfo    gatherInfo;
  290.  
  291.     WishGetCompareProc(aWindow, &compareProc, FALSE);
  292.     getAttrsP = WISH_ATTR_NECESSARY_P; 
  293.  
  294.     gatherInfo.aWindow = aWindow;
  295.     gatherInfo.grpPtr = grpPtr;
  296.     scanData = (ClientData) &gatherInfo;
  297.     nitems = scandir(aWindow->dir, &namelist, SelectGroupFiles, compareProc);
  298.     if (nitems < 0) {
  299.     sprintf(aWindow->interp->result, "%s %s %s %s.  %s %s",
  300.         "Directory scan failed in", aWindow->dir, "with error",
  301.         Stat_GetMsg(errno),
  302.         "Either the direcotry doesn't exist, or it",
  303.         "is unreadable, or we've run out of memory");
  304.     return TCL_ERROR;
  305.     }
  306.     /* since they're initialized to -1 */
  307.     if (aWindow->numElements == UNINITIALIZED) {
  308.     aWindow->numElements = 0;
  309.     }
  310.     if (aWindow->numHiddenGroups == UNINITIALIZED) {
  311.     aWindow->numHiddenGroups = 0;
  312.     }
  313.     for (i = 0; i < nitems; i++) {
  314.     if (getAttrsP) {
  315.         /*
  316.          * If the files were sorted by something involving an attribute,
  317.          * then there should be a way in the sort routines to cache that
  318.          * info so we don't do a second GetAttributes()'s here...
  319.          * This means dealing with the garbage collection aspects too.
  320.          */
  321.         if (lstat(namelist[i]->d_name, &attrs)
  322.             != 0) {
  323.         char    buffer[MAXPATHLEN];
  324.         sprintf(wishErrorMsg, "%s %s.  %s %s.  %s %s.",
  325.             "Couldn't get attributes for file",
  326.             namelist[i]->d_name,
  327.             "Error was",
  328.             Stat_GetMsg(errno),
  329.             "Current dir is",
  330.             getwd(buffer) == NULL ? "NULL" : buffer);
  331.         aWindow->notifierP = TRUE;
  332.         Sx_Notify(wishDisplay, aWindow->surroundingWindow, -1, -1, 0,
  333.             wishErrorMsg,
  334.             NULL, TRUE, "Leave attributes blank", (char *) NULL);
  335.         aWindow->notifierP = FALSE;
  336.         bzero(&attrs, sizeof (struct    stat));;
  337.         }
  338.     }
  339.     tmpPtr = (WishFile *) malloc(sizeof (WishFile));
  340.     tmpPtr->name = Util_Strcpy(NULL, namelist[i]->d_name);
  341.     if (getAttrsP) {
  342.         tmpPtr->attrPtr = (struct    stat *)
  343.             malloc(sizeof (struct    stat));
  344.         *(tmpPtr->attrPtr) = attrs;
  345.     } else {
  346.         tmpPtr->attrPtr = NULL;
  347.     }
  348.     tmpPtr->length = -1;
  349.     tmpPtr->x = tmpPtr->y = -1;
  350.     tmpPtr->myColumn = -1;
  351.     tmpPtr->selectedP = FALSE;
  352.     tmpPtr->lineP = FALSE;
  353.     tmpPtr->highlightP = FALSE;
  354.     tmpPtr->myGroupPtr = grpPtr;
  355.     tmpPtr->nextPtr = NULL;
  356.     if (grpPtr->fileList == NULL) {
  357.         grpPtr->fileList = tmpPtr;
  358.     } else {
  359.         /* add file to end of list */
  360.         for (backTmpPtr = grpPtr->fileList;
  361.             backTmpPtr->nextPtr != NULL;
  362.             backTmpPtr = backTmpPtr->nextPtr) {
  363.         /* do nothing */
  364.         }
  365.         backTmpPtr->nextPtr = tmpPtr;
  366.     }
  367.     aWindow->numElements++;
  368.     }
  369.     if (aWindow->numGroups == UNINITIALIZED) {
  370.     aWindow->numGroups = 1;
  371.     aWindow->numHiddenGroups = 0;
  372.     } else {
  373.     aWindow->numGroups++;
  374.     }
  375.     if (aWindow->hideEmptyGroupsP) {
  376.     if (grpPtr->fileList == NULL) {
  377.         aWindow->numHiddenGroups++;
  378.     }
  379.     }
  380.     /*
  381.      * Total number of things that could be displayed is the number of files
  382.      * plus the number of visible group headers plus the number of spaces
  383.      * between visible groups.
  384.      */
  385.     aWindow->totalDisplayEntries = aWindow->numElements +
  386.         (2 * (aWindow->numGroups - aWindow->numHiddenGroups)) - 1;
  387.     free_scandir(nitems, &namelist);
  388.  
  389.     return TCL_OK;
  390. }
  391.  
  392.  
  393. /*
  394.  *----------------------------------------------------------------------
  395.  *
  396.  * SelectFiles --
  397.  *
  398.  *    Routine passed to scandir(). 
  399.  *
  400.  * Results:
  401.  *    Return TRUE or FALSE depending
  402.  *    upon whether or not there's a group with a rule that would
  403.  *    select this the given file.
  404.  *
  405.  * Side effects:
  406.  *    None.
  407.  *
  408.  *----------------------------------------------------------------------
  409.  */
  410. Boolean
  411. SelectFiles(entryPtr)
  412.     struct    direct    *entryPtr;
  413. {
  414.     WishWindow    *aWindow;
  415.     WishGroup        *grpPtr;
  416.     int            result;
  417.  
  418.     aWindow = (WishWindow *) scanData;
  419.     for (grpPtr = aWindow->groupList; grpPtr != NULL;
  420.         grpPtr = grpPtr->nextPtr) {
  421.     result = Pattern_Match(grpPtr->rule, entryPtr->d_name);
  422.     if (result == 0) {
  423.         break;
  424.     } else if (result < 0) {
  425.         /*
  426.          * I must check the rules as they are created, or the following
  427.          * would cause a billion notifiers!
  428.          */
  429.         sprintf(wishErrorMsg, "The rule %s contains an error.",
  430.         grpPtr->rule);
  431.         aWindow->notifierP = TRUE;
  432.         Sx_Notify(wishDisplay, aWindow->displayWindow, -1, -1, 0,
  433.             wishErrorMsg, NULL, TRUE, "Continue", NULL);
  434.         aWindow->notifierP = FALSE;
  435.     }
  436.     }
  437.     if (grpPtr == NULL) {
  438.     return FALSE;
  439.     }
  440.     return TRUE;
  441. }
  442.  
  443.  
  444. /*
  445.  *----------------------------------------------------------------------
  446.  *
  447.  * SelectGroupFiles --
  448.  *
  449.  *    Routine passed to scandir() for selecting files for a single group. 
  450.  *
  451.  * Results:
  452.  *    Return TRUE or FALSE depending
  453.  *    upon whether or not the given group rule will select the given file.
  454.  *
  455.  * Side effects:
  456.  *    None.
  457.  *
  458.  *----------------------------------------------------------------------
  459.  */
  460. Boolean
  461. SelectGroupFiles(entryPtr)
  462.     struct    direct    *entryPtr;
  463. {
  464.     WishGroup        *grpPtr;
  465.     int            result;
  466.     WishWindow    *aWindow;
  467.  
  468.     aWindow = ((GatherInfo *) scanData)->aWindow;
  469.     grpPtr = ((GatherInfo *) scanData)->grpPtr;
  470.     if (grpPtr->defType == COMPARISON) {
  471.     result = Pattern_Match(grpPtr->rule, entryPtr->d_name);
  472.     if (result == 0) {
  473.         return TRUE;
  474.     } else if (result < 0) {
  475.         sprintf(wishErrorMsg, "The rule %s contains an error.",
  476.         grpPtr->rule);
  477.         aWindow->notifierP = TRUE;
  478.         Sx_Notify(wishDisplay, aWindow->displayWindow, -1, -1, 0,
  479.             wishErrorMsg, NULL, TRUE, "Continue", NULL);
  480.         aWindow->notifierP = FALSE;
  481.     }
  482.     return FALSE;
  483.     }
  484.     if (grpPtr->defType != PROC) {
  485.     aWindow->notifierP = TRUE;
  486.     Sx_Notify(wishDisplay, aWindow->displayWindow, -1, -1, 0,
  487.         "unknown type of rule definition", NULL,
  488.         TRUE, "Continue", NULL);
  489.     aWindow->notifierP = FALSE;
  490.     return FALSE;
  491.     }
  492.     if (WishDoTclSelect(aWindow->interp, grpPtr->rule, entryPtr->d_name,
  493.         &result) != TCL_OK) {
  494.     aWindow->notifierP = TRUE;
  495.     Sx_Notify(wishDisplay, aWindow->displayWindow, -1, -1, 0,
  496.         aWindow->interp->result, NULL, TRUE, "Continue", NULL);
  497.     aWindow->notifierP = FALSE;
  498.     return FALSE;
  499.     }
  500.     return result;
  501. }
  502.  
  503.  
  504. /*
  505.  *----------------------------------------------------------------------
  506.  *
  507.  * WishDoTclSelect --
  508.  *
  509.  *    Execute the tcl rule procName on the fileName arg and determine
  510.  *    whether the file matches the rule.
  511.  *
  512.  * Results:
  513.  *    TCL_OK if things work ok, and TCL_ERROR if not.  If the routine
  514.  *    returns TCL_OK, then boolean value
  515.  *    determining whether the file matches the rule is returned in the
  516.  *    selectValPtr parameter.
  517.  *
  518.  * Side effects:
  519.  *    None.
  520.  *
  521.  *----------------------------------------------------------------------
  522.  */
  523. int
  524. WishDoTclSelect(interp, procName, arg, selectValPtr)
  525.     Tcl_Interp        *interp;
  526.     char        *procName;
  527.     char        *arg;
  528.     int            *selectValPtr;
  529. {
  530.     char    *buffer;
  531.     char    *cPtr;
  532.  
  533.     if (procName == NULL || arg == NULL) {
  534.     strcpy(interp->result,
  535.         "Null procedure name or argument for file selection");
  536.     return TCL_ERROR;
  537.     }
  538.     buffer = (char *) malloc(strlen(procName) + strlen(arg) + 2);
  539.     sprintf(buffer, "%s %s", procName, arg);
  540.     if (Tcl_Eval(interp, buffer, '\0', NULL) != TCL_OK) {
  541.     sprintf(interp->result,
  542.         "Something is wrong with the rule definition %s.", procName);
  543.     free(buffer);
  544.     return TCL_ERROR;
  545.     }
  546.     free(buffer);
  547.     if ((*selectValPtr = strtol(interp->result, &cPtr, 10)) == 0
  548.         && cPtr == interp->result) {
  549.     sprintf(interp->result, "Bad proc definition %s", procName);
  550.     return TCL_ERROR;
  551.     }
  552.     if (*selectValPtr < 0) {
  553.     sprintf(interp->result, "proc %s returned an error value", procName);
  554.     return TCL_ERROR;
  555.     }
  556.     /* reverse the meaning, since pattern match returns 0 for success... */
  557.     if (*selectValPtr == 0) {
  558.     *selectValPtr = 1;
  559.     } else {
  560.     *selectValPtr = 0;
  561.     }
  562.     return TCL_OK;
  563. }
  564.  
  565.  
  566. /*
  567.  *----------------------------------------------------------------------
  568.  *
  569.  * AlphaForwards --
  570.  *
  571.  *    Compare two files for alphabetical order.
  572.  *
  573.  * Results:
  574.  *    Negative if the first is before the second.  Zero if they are the
  575.  *    same.  Positive if the first is after the second.
  576.  *
  577.  * Side effects:
  578.  *    None.
  579.  *
  580.  *----------------------------------------------------------------------
  581.  */
  582. int
  583. AlphaForwards(first, second)
  584.     struct    direct    **first, **second;
  585. {
  586.     return alphasort(first, second);
  587. }
  588.  
  589.  
  590. /*
  591.  *----------------------------------------------------------------------
  592.  *
  593.  * AlphaReverse --
  594.  *
  595.  *    Compare two files for reverse alphabetical order.
  596.  *
  597.  * Results:
  598.  *    Negative if the first is before the second.  Zero if they are the
  599.  *    same.  Positive if the first is after the second.
  600.  *
  601.  * Side effects:
  602.  *    None.
  603.  *
  604.  *----------------------------------------------------------------------
  605.  */
  606. int
  607. AlphaReverse(first, second)
  608.     struct    direct    **first, **second;
  609. {
  610.     return (-alphasort(first, second));
  611. }
  612.  
  613.  
  614. int
  615. AtimeForwards(first, second)
  616.     struct    direct    **first, **second;
  617. {
  618.     return AtimeSort(first, second);
  619. }
  620.  
  621. int
  622. AtimeReverse(first, second)
  623.     struct    direct    **first, **second;
  624. {
  625.     return (-AtimeSort(first, second));
  626. }
  627.  
  628. #ifdef NOTDEF
  629. int
  630. CtimeForwards(first, second)
  631.     struct    direct    **first, **second;
  632. {
  633.     return CtimeSort(first, second);
  634. }
  635.  
  636. int
  637. CtimeReverse(first, second)
  638.     struct    direct    **first, **second;
  639. {
  640.     return (-CtimeSort(first, second));
  641. }
  642. #endif /* NOTDEF */
  643.  
  644. int
  645. MtimeForwards(first, second)
  646.     struct    direct    **first, **second;
  647. {
  648.     return MtimeSort(first, second);
  649. }
  650.  
  651. int
  652. MtimeReverse(first, second)
  653.     struct    direct    **first, **second;
  654. {
  655.     return (-MtimeSort(first, second));
  656. }
  657.  
  658. int
  659. DtimeForwards(first, second)
  660.     struct    direct    **first, **second;
  661. {
  662.     return DtimeSort(first, second);
  663. }
  664.  
  665. int
  666. DtimeReverse(first, second)
  667.     struct    direct    **first, **second;
  668. {
  669.     return (-DtimeSort(first, second));
  670. }
  671.  
  672. int
  673. SizeForwards(first, second)
  674.     struct    direct    **first, **second;
  675. {
  676.     return SizeSort(first, second);
  677. }
  678.  
  679. int
  680. SizeReverse(first, second)
  681.     struct    direct    **first, **second;
  682. {
  683.     return (-SizeSort(first, second));
  684. }
  685.  
  686. static int
  687. FileAlphaSort(file1, file2)
  688.     WishFile    **file1;
  689.     WishFile    **file2;
  690. {
  691.     return strcmp((*file1)->name, (*file2)->name);
  692. }
  693.  
  694. static int
  695. FileAlphaReverseSort(file1, file2)
  696.     WishFile    **file1;
  697.     WishFile    **file2;
  698. {
  699.     return (-strcmp((*file1)->name, (*file2)->name));
  700. }
  701.  
  702. static int
  703. AtimeCompare(attrs1, attrs2)
  704.     struct    stat    *attrs1;
  705.     struct    stat    *attrs2;
  706. {
  707.     if (attrs1->st_atime > attrs2->st_atime) {
  708.     return -1;
  709.     }
  710.     if (attrs1->st_atime< attrs2->st_atime) {
  711.     return 1;
  712.     }
  713. #ifdef NOTDEF
  714.     /*
  715.      * What to do about this?  Sprite gives microseconds as well as
  716.      * seconds...
  717.      */
  718.     if (attrs1->st_atime.microseconds > attrs2->st_atime.microseconds) {
  719.     return -1;
  720.     }
  721.     if (attrs1->st_atime.microseconds < attrs2->st_atime.microseconds) {
  722.     return 1;
  723.     }
  724. #endif /* NOTDEF */
  725.     return 0;
  726. }
  727.  
  728. static int
  729. FileAtimeSort(file1, file2)
  730.     WishFile    **file1;
  731.     WishFile    **file2;
  732. {
  733.     return AtimeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  734. }
  735.  
  736. static int
  737. FileAtimeReverseSort(file1, file2)
  738.     WishFile    **file1;
  739.     WishFile    **file2;
  740. {
  741.     return (-AtimeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  742. }
  743.  
  744. static    int
  745. AtimeSort(d1, d2)
  746.     struct    direct    **d1, **d2;
  747. {
  748.     struct    stat    attrs1;
  749.     struct    stat    attrs2;
  750.  
  751.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  752.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  753.         (*d1)->d_name);
  754.     /* Is panic the right thing? */
  755.     Sx_Panic(wishDisplay, wishErrorMsg);
  756.     }
  757.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  758.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  759.         (*d2)->d_name);
  760.     /* Is panic the right thing? */
  761.     Sx_Panic(wishDisplay, wishErrorMsg);
  762.     }
  763.     return AtimeCompare(&attrs1, &attrs2);
  764.  
  765. }
  766.  
  767. #ifdef NOTDEF
  768. static int
  769. CtimeCompare(attrs1, attrs2)
  770.     struct    stat    *attrs1;
  771.     struct    stat    *attrs2;
  772. {
  773.     if (attrs1->createTime.seconds > attrs2->createTime.seconds) {
  774.     return -1;
  775.     }
  776.     if (attrs1->createTime.seconds < attrs2->createTime.seconds) {
  777.     return 1;
  778.     }
  779.     if (attrs1->createTime.microseconds > attrs2->createTime.microseconds) {
  780.     return -1;
  781.     }
  782.     if (attrs1->createTime.microseconds < attrs2->createTime.microseconds) {
  783.     return 1;
  784.     }
  785.     return 0;
  786. }
  787.  
  788. static int
  789. FileCtimeSort(file1, file2)
  790.     WishFile    **file1;
  791.     WishFile    **file2;
  792. {
  793.     return CtimeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  794. }
  795.  
  796. static int
  797. FileCtimeReverseSort(file1, file2)
  798.     WishFile    **file1;
  799.     WishFile    **file2;
  800. {
  801.     return (-CtimeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  802. }
  803.  
  804. static    int
  805. CtimeSort(d1, d2)
  806.     struct    direct    **d1, **d2;
  807. {
  808.     struct    stat    attrs1;
  809.     struct    stat    attrs2;
  810.  
  811.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  812.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  813.         (*d1)->d_name);
  814.     /* Is panic the right thing? */
  815.     Sx_Panic(wishDisplay, wishErrorMsg);
  816.     }
  817.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  818.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  819.         (*d2)->d_name);
  820.     /* Is panic the right thing? */
  821.     Sx_Panic(wishDisplay, wishErrorMsg);
  822.     }
  823.     return CtimeCompare(&attrs1, &attrs2);
  824. }
  825. #endif /* NOTDEF */
  826.  
  827. static int
  828. MtimeCompare(attrs1, attrs2)
  829.     struct    stat    *attrs1;
  830.     struct    stat    *attrs2;
  831. {
  832.     if (attrs1->st_mtime > attrs2->st_mtime) {
  833.     return -1;
  834.     }
  835.     if (attrs1->st_mtime < attrs2->st_mtime) {
  836.     return 1;
  837.     }
  838. #ifdef NOTDEF
  839.     if (attrs1->dataModifyTime.microseconds >
  840.         attrs2->dataModifyTime.microseconds) {
  841.     return -1;
  842.     }
  843.     if (attrs1->dataModifyTime.microseconds <
  844.         attrs2->dataModifyTime.microseconds) {
  845.     return 1;
  846.     }
  847. #endif /* NOTDEF */
  848.     return 0;
  849. }
  850.  
  851. static int
  852. FileMtimeSort(file1, file2)
  853.     WishFile    **file1;
  854.     WishFile    **file2;
  855. {
  856.     return MtimeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  857. }
  858.  
  859. static int
  860. FileMtimeReverseSort(file1, file2)
  861.     WishFile    **file1;
  862.     WishFile    **file2;
  863. {
  864.     return (-MtimeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  865. }
  866.  
  867. static    int
  868. MtimeSort(d1, d2)
  869.     struct    direct    **d1, **d2;
  870. {
  871.     struct    stat    attrs1;
  872.     struct    stat    attrs2;
  873.  
  874.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  875.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  876.         (*d1)->d_name);
  877.     /* Is panic the right thing? */
  878.     Sx_Panic(wishDisplay, wishErrorMsg);
  879.     }
  880.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  881.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  882.         (*d2)->d_name);
  883.     /* Is panic the right thing? */
  884.     Sx_Panic(wishDisplay, wishErrorMsg);
  885.     }
  886.     return MtimeCompare(&attrs1, &attrs2);
  887. }
  888.  
  889. static int
  890. DtimeCompare(attrs1, attrs2)
  891.     struct    stat    *attrs1;
  892.     struct    stat    *attrs2;
  893. {
  894.     if (attrs1->st_ctime > attrs2->st_ctime) {
  895.     return -1;
  896.     }
  897.     if (attrs1->st_ctime < attrs2->st_ctime) {
  898.     return 1;
  899.     }
  900. #ifdef NOTDEF
  901.     if (attrs1->st_ctime.microseconds > attrs2->st_ctime.microseconds) {
  902.     return -1;
  903.     }
  904.     if (attrs1->st_ctime.microseconds < attrs2->st_ctime.microseconds) {
  905.     return 1;
  906.     }
  907. #endif /* NOTDEF */
  908.     return 0;
  909. }
  910.  
  911. static int
  912. FileDtimeSort(file1, file2)
  913.     WishFile    **file1;
  914.     WishFile    **file2;
  915. {
  916.     return DtimeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  917. }
  918.  
  919. static int
  920. FileDtimeReverseSort(file1, file2)
  921.     WishFile    **file1;
  922.     WishFile    **file2;
  923. {
  924.     return (-DtimeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  925. }
  926.  
  927. static    int
  928. DtimeSort(d1, d2)
  929.     struct    direct    **d1, **d2;
  930. {
  931.     struct    stat    attrs1;
  932.     struct    stat    attrs2;
  933.  
  934.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  935.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  936.         (*d1)->d_name);
  937.     /* Is panic the right thing? */
  938.     Sx_Panic(wishDisplay, wishErrorMsg);
  939.     }
  940.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  941.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  942.         (*d2)->d_name);
  943.     /* Is panic the right thing? */
  944.     Sx_Panic(wishDisplay, wishErrorMsg);
  945.     }
  946.     return DtimeCompare(&attrs1, &attrs2);
  947. }
  948.  
  949. static int
  950. SizeCompare(attrs1, attrs2)
  951.     struct    stat    *attrs1;
  952.     struct    stat    *attrs2;
  953. {
  954.     if (attrs1->st_size > attrs2->st_size) {
  955.     return 1;
  956.     }
  957.     if (attrs1->st_size < attrs2->st_size) {
  958.     return -1;
  959.     }
  960.     return 0;
  961. }
  962.  
  963. static int
  964. FileSizeSort(file1, file2)
  965.     WishFile    **file1;
  966.     WishFile    **file2;
  967. {
  968.     return SizeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  969. }
  970.  
  971. static int
  972. FileSizeReverseSort(file1, file2)
  973.     WishFile    **file1;
  974.     WishFile    **file2;
  975. {
  976.     return (-SizeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  977. }
  978.  
  979. static    int
  980. SizeSort(d1, d2)
  981.     struct    direct    **d1, **d2;
  982. {
  983.     struct    stat    attrs1;
  984.     struct    stat    attrs2;
  985.  
  986.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  987.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  988.         (*d1)->d_name);
  989.     /* Is panic the right thing? */
  990.     Sx_Panic(wishDisplay, wishErrorMsg);
  991.     }
  992.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  993.     sprintf(wishErrorMsg, "Couldn't get attributes for %s.",
  994.         (*d2)->d_name);
  995.     /* Is panic the right thing? */
  996.     Sx_Panic(wishDisplay, wishErrorMsg);
  997.     }
  998.     return SizeCompare(&attrs1, &attrs2);
  999. }
  1000.  
  1001.  
  1002. /*
  1003.  *----------------------------------------------------------------------
  1004.  *
  1005.  * WishGetCompareProc --
  1006.  *
  1007.  *    Figure out what the comparison routine is and return it in
  1008.  *    the compareProc parameter.
  1009.  *    If fileProcP is true, return a function that takes pointers
  1010.  *    to WishFiles.  Otherwise it takes struct    direct's.
  1011.  *
  1012.  * Results:
  1013.  *    None.
  1014.  *
  1015.  * Side effects:
  1016.  *    None.
  1017.  *
  1018.  *----------------------------------------------------------------------
  1019.  */
  1020. void
  1021. WishGetCompareProc(aWindow, compareProcPtr, fileProcP)
  1022.     WishWindow    *aWindow;
  1023.     int    (**compareProcPtr)();
  1024.     Boolean        fileProcP;    /* which comp func type */
  1025. {
  1026.     if (aWindow->sortingInstructions == 0) {
  1027.     aWindow->sortingInstructions = WISH_ALPHA_SORT;    /* default */
  1028.     }
  1029.     if (aWindow->sortingInstructions & WISH_REVERSE_SORT) {
  1030.     if (aWindow->sortingInstructions & WISH_ALPHA_SORT) {
  1031.         if (fileProcP) {
  1032.         *compareProcPtr = FileAlphaReverseSort;
  1033.         } else {
  1034.         *compareProcPtr = AlphaReverse;
  1035.         }
  1036.     } else if (aWindow->sortingInstructions & WISH_ATIME_SORT) {
  1037.         if (fileProcP) {
  1038.         *compareProcPtr = FileAtimeReverseSort;
  1039.         } else {
  1040.         *compareProcPtr = AtimeReverse;
  1041.         }
  1042. #ifdef NOTDEF
  1043.     } else if (aWindow->sortingInstructions & WISH_CTIME_SORT) {
  1044.         if (fileProcP) {
  1045.         *compareProcPtr = FileCtimeReverseSort;
  1046.         } else {
  1047.         *compareProcPtr = CtimeReverse;
  1048.         }
  1049. #endif NOTDEF
  1050.     } else if (aWindow->sortingInstructions & WISH_MTIME_SORT) {
  1051.         if (fileProcP) {
  1052.         *compareProcPtr = FileMtimeReverseSort;
  1053.         } else {
  1054.         *compareProcPtr = MtimeReverse;
  1055.         }
  1056.     } else if (aWindow->sortingInstructions & WISH_DTIME_SORT) {
  1057.         if (fileProcP) {
  1058.         *compareProcPtr = FileDtimeReverseSort;
  1059.         } else {
  1060.         *compareProcPtr = DtimeReverse;
  1061.         }
  1062.     } else if (aWindow->sortingInstructions & WISH_SIZE_SORT) {
  1063.         if (fileProcP) {
  1064.         *compareProcPtr = FileSizeReverseSort;
  1065.         } else {
  1066.         *compareProcPtr = SizeReverse;
  1067.         }
  1068.     }
  1069.     } else {
  1070.     if (aWindow->sortingInstructions & WISH_ALPHA_SORT) {
  1071.         if (fileProcP) {
  1072.         *compareProcPtr = FileAlphaSort;
  1073.         } else {
  1074.         *compareProcPtr = AlphaForwards;
  1075.         }
  1076.     } else if (aWindow->sortingInstructions & WISH_ATIME_SORT) {
  1077.         if (fileProcP) {
  1078.         *compareProcPtr = FileAtimeSort;
  1079.         } else {
  1080.         *compareProcPtr = AtimeForwards;
  1081.         }
  1082. #ifdef NOTDEF
  1083.     } else if (aWindow->sortingInstructions & WISH_CTIME_SORT) {
  1084.         if (fileProcP) {
  1085.         *compareProcPtr = FileCtimeSort;
  1086.         } else {
  1087.         *compareProcPtr = CtimeForwards;
  1088.         }
  1089. #endif /* NOTDEF */
  1090.     } else if (aWindow->sortingInstructions & WISH_MTIME_SORT) {
  1091.         if (fileProcP) {
  1092.         *compareProcPtr = FileMtimeSort;
  1093.         } else {
  1094.         *compareProcPtr = MtimeForwards;
  1095.         }
  1096.     } else if (aWindow->sortingInstructions & WISH_DTIME_SORT) {
  1097.         if (fileProcP) {
  1098.         *compareProcPtr = FileDtimeSort;
  1099.         } else {
  1100.         *compareProcPtr = DtimeForwards;
  1101.         }
  1102.     } else if (aWindow->sortingInstructions & WISH_SIZE_SORT) {
  1103.         if (fileProcP) {
  1104.         *compareProcPtr = FileSizeSort;
  1105.         } else {
  1106.         *compareProcPtr = SizeForwards;
  1107.         }
  1108.     }
  1109.     }
  1110.  
  1111.     return;
  1112. }
  1113.